package com.CityHunter.OverLay;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;

import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.app.DatePickerDialog;
import android.app.TimePickerDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.Paint.Style;
import android.graphics.Path;
import android.graphics.Point;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.DatePicker;
import android.widget.EditText;
import android.widget.TimePicker;

import com.CityHunter.R;
import com.CityHunter.DataObject.Schedule;
import com.CityHunter.Request.DirectionAPIRequest;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;

public class TouchOverLay extends Overlay {

	private Context context;
	private int drawable;
	private ArrayList<GeoPoint> path;
	private Schedule schedule;
	private GeoPoint currentGeoPoint;
	private int mYear, mMonth, mDay, mHour, mMinute;

	private Date selectedDate;

	private Button schedule_btn_date, schedule_btn_time;
	private EditText schedule_et_desc;

	public TouchOverLay(Context context, int drawable, Schedule schedule) {
		this.context = context;
		this.drawable = drawable;
		this.schedule = schedule;
		path = new ArrayList<GeoPoint>();
	}

	@Override
	public boolean onTap(GeoPoint geoPoint, MapView mapView) {
		super.onTap(geoPoint, mapView);

		updateDate();

		currentGeoPoint = geoPoint;
		showScheduleAlertMenu();

		return true;
	}

	@Override
	public boolean draw(Canvas canvas, MapView mapView, boolean shadow,
			long when) {

		// Draw Schedule Points
		for (int i = 0; i < schedule.size(); i++) {

			Paint p = new Paint();
			Point out = new Point();
			mapView.getProjection().toPixels(schedule.get(i).geoPoint(), out);
			
			GeoPoint geoPoint = schedule.get(i).geoPoint();
			// Convert geo coordinates to screen pixels
			Point screenPoint = new Point();
			mapView.getProjection().toPixels(geoPoint, screenPoint);

			// Read the image
			Bitmap scheduleMarker = BitmapFactory.decodeResource(
					context.getResources(), drawable);
			
			printDesc(out,canvas,p,i);
			
			// Draw it, centered around the given coordinates
			canvas.drawBitmap(scheduleMarker,
					screenPoint.x - scheduleMarker.getWidth() / 2,
					screenPoint.y - scheduleMarker.getHeight() / 2, null);
			
		}

		// Draw Schedule Path
		if (path.size() > 0) {

			Paint p = new Paint();
			Point out = new Point();
			Path myPath = new Path();

			for (int i = 0; i < path.size(); i++) {
				//Point out = new Point();
				mapView.getProjection().toPixels(path.get(i), out);

				if (i == 0) {
					myPath.moveTo(out.x, out.y);
					// printDesc(out, canvas, p, i);
				} else if (i != path.size()) {
					myPath.lineTo(out.x, out.y);
					// printDesc(out, canvas, p, i);
				} else {
					myPath.setLastPoint(out.x, out.y);
					// printDesc(out, canvas, p, i);
				}

			}

			p.setColor(Color.RED);
			p.setStyle(Style.STROKE);
			p.setStrokeWidth(10);
			p.setAlpha(70);

			canvas.drawPath(myPath, p);
		}
		super.draw(canvas, mapView, shadow);
		return true;
	}

	public void printDesc(Point out, Canvas canvas, Paint p, int i) {
		int[] scoords = new int[2];
		int sz = 5;

		scoords[0] = out.x;
		scoords[1] = out.y;
		int sw = (int) (p.measureText(schedule.get(i).toString()) + 0.5f);
		int sh = 25;
		int sx = scoords[0] - sw / 2 - 5;
		int sy = scoords[1] - sh - sz - 2;
		RectF rec = new RectF(sx, sy, sx + sw + 10, sy + sh);

		p.setStyle(Style.FILL);
		p.setColor(Color.BLACK);

		canvas.drawRoundRect(rec, 5, 5, p);

		p.setStyle(Style.STROKE);
		p.setARGB(255, 255, 255, 255);
		canvas.drawRoundRect(rec, 5, 5, p);
		// canvas.d

		canvas.drawText(schedule.get(i).toString(), sx + 5, sy + sh - 8, p);

		// Draw point body and outer ring
		p.setStyle(Style.FILL);
		p.setColor(Color.BLUE);
		p.setStrokeWidth(1);
		RectF spot = new RectF(scoords[0] - sz, scoords[1] + sz, scoords[0]
				+ sz, scoords[1] - sz);
		canvas.drawOval(spot, p);

		p.setARGB(255, 255, 0, 0);
		p.setStyle(Style.STROKE);
		canvas.drawCircle(scoords[0], scoords[1], sz, p);
		
	}

	private void showScheduleAlertMenu() {

		LayoutInflater factory = LayoutInflater.from(context);
		View addSchedulePointView = factory.inflate(
				R.layout.add_schedule_point_dialog, null);

		schedule_btn_date = (Button) addSchedulePointView
				.findViewById(R.id.schedule_btn_date);
		schedule_btn_time = (Button) addSchedulePointView
				.findViewById(R.id.schedule_btn_time);

		schedule_et_desc = (EditText) addSchedulePointView
				.findViewById(R.id.schedule_et_desc);

		schedule_btn_date.setText(dateToString(selectedDate));
		schedule_btn_date.setOnClickListener(handleEditDate);
		schedule_btn_time.setText(timeToString(selectedDate));
		schedule_btn_time.setOnClickListener(handleEditTime);

		Builder addSchedulePointDialog = new AlertDialog.Builder(context)
				.setTitle(R.string.lbl_addPoint).setView(addSchedulePointView)
				.setPositiveButton(R.string.lbl_addPoint, handleAddPointButton)
				.setNegativeButton(R.string.lbl_cancel, null);
		addSchedulePointDialog.show();
	}

	// Listener Handling Alert Menu
	private OnClickListener handleAddPointButton = new DialogInterface.OnClickListener() {

		@Override
		public void onClick(DialogInterface dialog, int which) {
			// handle add GeoPoint
			String description = schedule_et_desc.getText().toString();
			schedule.addPoint(currentGeoPoint, selectedDate, description);
			if (schedule.size() > 1)
				updatePath();
			Log.d("Debug", schedule.toString());
		}
	};

	// Implement button register on click listener
	private View.OnClickListener handleEditDate = new View.OnClickListener() {
		@Override
		public void onClick(View rv) {

			Log.d("Debug", "selectedDate = " + selectedDate.toString());

			new DatePickerDialog(context,
					new DatePickerDialog.OnDateSetListener() {
						public void onDateSet(DatePicker view, int year,
								int month, int day) {
							mYear = year;
							mMonth = month;
							mDay = day;
							setDate();
							schedule_btn_date
									.setText(dateToString(selectedDate));
						}
					}, mYear, mMonth, mDay).show();

		}
	};

	// Implement button register on click listener
	private View.OnClickListener handleEditTime = new View.OnClickListener() {
		@Override
		public void onClick(View v) {

			new TimePickerDialog(context,
					new TimePickerDialog.OnTimeSetListener() {
						public void onTimeSet(TimePicker view, int hour,
								int minute) {
							mHour = hour;
							mMinute = minute;
							setDate();
							schedule_btn_time
									.setText(timeToString(selectedDate));
						}
					}, mHour, mMinute, true).show();
			schedule_btn_time.setText(timeToString(selectedDate));

		}
	};

	private void updateDate() {
		Calendar c = Calendar.getInstance();
		mYear = c.get(Calendar.YEAR);
		mMonth = c.get(Calendar.MONTH);
		mDay = c.get(Calendar.DAY_OF_MONTH);
		mHour = c.get(Calendar.HOUR_OF_DAY);
		mMinute = c.get(Calendar.MINUTE);

		setDate();

		Log.d("Debug", "selectedDate Year = " + selectedDate.getYear()
				+ " selectedDate Month = " + selectedDate.getMonth()
				+ " selectedDate Day = " + selectedDate.getDate());
		Log.d("Debug", "selectedDate Hour = " + selectedDate.getHours()
				+ " selectedDate Minute = " + selectedDate.getMinutes());
	}

	private void updatePath() {
		DirectionAPIRequest dirReq = new DirectionAPIRequest(
				context.getString(R.string.url_directionAPIPage));
		path = dirReq.directionAPI(schedule);
	}

	private void setDate() {
		selectedDate = new Date(mYear, mMonth, mDay, mHour, mMinute);
	}

	private String dateToString(Date date) {
		return date.getDate() + "/" + (date.getMonth() + 1) + "/"
				+ date.getYear();

	}

	private String timeToString(Date date) {
		return date.getHours() + ":" + date.getMinutes();
	}
}
